import { _decorator, Component, error, Node, Sprite } from 'cc';
import { HImageResource } from './HResource';
import { defined } from '../hyxh/core/Defined';
import { IParametersOptions } from '../hyxh/core/HBase';
import { SecenesManager } from './SecenesManager';
import { SecenseTools } from './SecenseTools';
import { SpritePlayer } from './SpritePlayer';
import { BelialHunter } from './BelialHunter';
import { HNetsPolyline } from '../hyxh/core/HYXHNetsPolyline';
import { Check } from '../hyxh/core/Check';
import { ICartesian } from "../hyxh/core/Cartesian"; 
import { Cion } from './cion';
const { ccclass, property } = _decorator;

@ccclass('ElevatorController')
export class ElevatorController extends Component {
    
    /**
     * cocos 的精灵或者图片对象
     */
    private _image = 0; 
    private _path = -1;
    private _speed = 0.05;
    private _startindex = -1;
    private _endindex = -1;
    private waittings: number[] = [];       // 当SpritePlay 达到此位置后，电梯启动
    private onboards: number[] = [];        // 精灵登陆位置
    
    thisNode: Node = null;
    /**
     * 方向, 1 为正向， -1 为反向
     */
    private _direction = 1;
    /**
     * 当前位置
     */
    private _current_index = 0;
    
    /* 精灵位置检索点 */
    private _node_pos: Cion = null!;
    
    /** 图像资源 */
    private _spriteFrame: HImageResource = null!;

    /* 活跃状态, 激活后，启动跳跃 */
    public activity: boolean = false;
    /* 乘客, 用于进行电梯联动 */
    private passenger: SpritePlayer | BelialHunter | null = null;
    /* 电梯行经路径 */
    private elevator_path_queue: Array<ICartesian> = [];
    
    public setPassenger(passenger: SpritePlayer | BelialHunter) {
        this.passenger = passenger;
    }
 
    public getPassenger(): SpritePlayer | BelialHunter | null {
        return this.passenger;
    }
 
    public passengerLeave() {
        this.passenger = null;
    }

    public isActivity(): boolean{
        return this.activity;
    }

    public hasPassenger(): boolean {
        return defined(this.passenger);
    }

    public runElevator() {
        this.activity = true;
    }

    public nextPosForLeaveElevator(_node_pos: Cion) : boolean {
        if (!defined(this._secenController)) {
            error("option seceneController is null!");
        }
        if(!defined(_node_pos)) {
            return true;
        }
        /* 主要是判断，是否在电梯的范围内 */
        if(!defined(_node_pos.points)) {
            return true;
        }
        if (_node_pos.points.length <= 0) {
            return true;
        }
        /* 当前cion 对应pos 已经在电梯 */
        if(_node_pos.forInRange(this._path, this._startindex, this._endindex)) {
            return false;
        }
        return true;
    }

    /**
     * 预判，下个Post位置，是进入或者即将进入电梯
     * @param _node_pos 
     */
    public nextPosForElevator(_node_pos: Cion) : boolean {
        if (!defined(this._secenController)) {
            error("option seceneController is null!");
        }
        if(!defined(_node_pos)) {
            return false;
        }
        /* 主要是判断，是否在电梯的范围内 */
        if(!defined(_node_pos.points)) {
            return false;
        }
        if (_node_pos.points.length <= 0) {
            return false;
        }
        /* 当前cion 对应pos 已经在电梯 */
        if(_node_pos.forInRange(this._path, this._startindex, this._endindex)) {
            return true;
        }
        
        let _cursor_index = 0;
        while( _cursor_index < this.waittings.length ) {
            const _cur_layer = this.waittings[_cursor_index++]; 
            _cursor_index++
            if (_node_pos.hasSamePath(_cur_layer)) {
                return true;
            }
        }
        return false;
    }

    public generateElevatorPathForRunElevator() {
        if (!defined(this._secenController)) {
            error("option seceneController is null!");
        }
        if (!defined(this._node_pos)) {
            error("option path is null!");
        }
        const length = this._secenController.getNetWork().getPathSize(this._path);
        if (!defined(length)) {
            return;
        }
        if (length <= 0 ){
            return;
        }
        
        let _start = this._startindex;
        let _end = this._endindex; 
        if (_start < 0 ){
            _start = length + _start;
        } 
        if (_end < 0 ){
            _end = length + _end;
        }
        if (!defined(this.elevator_path_queue)) {
            this.elevator_path_queue = [];
        } else if ( this.elevator_path_queue.length > 0) {
            this.elevator_path_queue.splice(0, this.elevator_path_queue.length);
        }
        
        let _target_start = -1;
        let _target_end = -1;

        if ( this._node_pos.hasExistPoints(this._path, _start)) {
            _target_start = _start;
            _target_end = _end;
        } else {
            _target_start = _end;
            _target_end = _start;
        }

        const _t_new_path = this._secenController.getNetWork().navigationMinDist(
            this._path,
            _target_start,
            this._path,
            _target_end);
        if (defined(_t_new_path) && (_t_new_path.length > 0)){
            this.elevator_path_queue.push(..._t_new_path);
            this.activity = true;
        } 
        
    }
    
    public generateElevatorPath(targ_pos: Cion) {
        if (!defined(this._secenController)) {
            error("option seceneController is null!");
        }
        
        if (!defined(this._node_pos)) {
            error("option path is null!");
        }
        if (!defined(this.elevator_path_queue)) {
            this.elevator_path_queue = [];
        } else if ( this.elevator_path_queue.length > 0) {
            this.elevator_path_queue.splice(0, this.elevator_path_queue.length);
        }

        const _t_new_path = this._secenController.getNetWork().navigationMinDist(
            this._node_pos.points[0],
            this._node_pos.points[1],
            targ_pos.points[0],
            targ_pos.points[1]);
        if (defined(_t_new_path) && (_t_new_path.length > 0)){
            this.elevator_path_queue.push(..._t_new_path);
            this.activity = true;
        } 
    }
    

    public moveForNodePos( new_node_pos: Cion) {
        if (!defined(new_node_pos)) {
            return;
        }
        this._node_pos = new_node_pos;
        this.thisNode.setPosition(this._node_pos.position.x, this._node_pos.position.y, this._node_pos.position.z);
        if (defined(this.passenger)) {
            this.passenger.moveForNodePos(this._node_pos);
        }
    }

    public getNodePos() {
        return this._node_pos;
    }

    @property('seceneController')
    private _secenController: SecenseTools = null!;

    private stimes: number = 0;
     /**
      * 获得对应的path
      * 
      * @returns 
      */
    public getPath(): number {
        return this._path;
    }

    /**
     * 
     * @param option 
     *          {
     *               "name": "elevatorE101H",
     *               "image":9001021,
     *               "path":  21,
     *               "speed": 0.05,
     *               "startindex": 0,
     *               "endindex": -1
     *           }
     */
    public initialize(option: IParametersOptions) {
        if (!defined(option)) {
            return; 
        }
        this._image = option.image;
        this.name = option.name;
        this._path = option.path;
        this._speed = option.speed;
        this._startindex = option.startindex;
        this._endindex = option.endindex;
        this.waittings = option.waittings;
        this.onboards = option.onboards;
        /* 设置为新的位置 */
        this._current_index = this._startindex;
        this.thisNode = new Node(this.name);
        this.thisNode.parent = this.node;        
    }

    public setSceneController(secenController: SecenseTools) {
        this._secenController = secenController; 
    }

    public loadResources() {        
        this.initSpriteImages(); 
    }

    public initSpriteImages() {
        if (!defined(this._secenController)) {
            error("option seceneController is null!");
        }
        const _path_index = this._path;
        const _p_index = this._startindex;
        if (!defined(_path_index)) {
            error("option path is null!");
        }

        if (!defined(_p_index)) {
            error("option point index is null!");
        }

        const _cion =  this._secenController.indexCion(_path_index, _p_index);
        if (!defined(_cion)) {
            error("path and point index is legal value , no cion has found!");
        }
        this._spriteFrame = SecenesManager.getInstance().getResource(this._image) as HImageResource;
        /* 显示传送门 */
        SecenesManager.showImage(this.thisNode, this._spriteFrame);
        /* 定位 */
        this.moveForNodePos(_cion);     
    }
    /**
     * 默认更新，用于跳跃
     * @param deltaTime 
     */
    update(deltaTime: number) {
        /* 进行移动 */
        this.stimes += deltaTime;
        if ( this.stimes >= this._speed ){
            if (this.activity) {                
                /* */
                this.movenext();
            }
            this.stimes = 0;
        }
    }

    stopElevator() {    
        this.activity = false;
        this.elevator_path_queue.splice(0, this.elevator_path_queue.length);
    }

    movenext() {
        if ( !defined(this.elevator_path_queue)) {
            this.activity = false;
            return;
        }
        if (this.elevator_path_queue.length == 0) {
            this.stopElevator();
            return;
        }

        /* 出栈 */
        const _next_pos = this.elevator_path_queue.shift();
        if (!defined(_next_pos)) {
            this.stopElevator();
            return;
        }
        let _node_pos = this._secenController.findNearestPoint(_next_pos);
        if (!defined(_next_pos)) {
            this.stopElevator();
            return;
        }

        if(!_node_pos.getElevatorSign()) {
            this.stopElevator();
            return;
        }
        this.moveForNodePos(_node_pos);
    }

    /**
     * 判断精灵是否到达等待位置
     * @param sprite_node_pos 
     */
    public isTouched(sprite_node_pos: Cion ): boolean {
        if (!defined(sprite_node_pos)) {
            return false;
        }
        if(!defined(this.waittings)) {
            return false;
        }
        if (this.waittings.length == 0){
            return false;
        }
        if(!defined(this._secenController)) {
            return false;
        }

        let index_cursor = 0;
        while( index_cursor < this.waittings.length ){
            const layer = this.waittings[index_cursor++];
            const point_index = this.waittings[index_cursor++];
            const cion = this._secenController.indexCion(layer, point_index);
            if (!defined(cion)) {
                continue;
            }
            if (cion.equalsPosition(sprite_node_pos)) {
                return true;
            }
        }
        return false;
    }   

    /**
     * 电梯移动，用于双向
     * @returns 
     */
    flushPath(): Cion | null {
        Check.defined("this._secenController", this._secenController);
        Check.typeOf.object("this._secenController", this._secenController);

        const _net_work = this._secenController.getNetWork();
        if (!defined(_net_work)) {
            return null;
        }

        const res = _net_work.getNextPoint(
            this._path, 
            this._current_index,
            this._direction,
            this._startindex, this._endindex );

        const _result = res.position;
        if (defined(res.nextindex)) {
            this._current_index = res.nextindex;
        }
        return this._secenController.indexCion(this._path, this._current_index);
    }
}


